#include "stdio.h"
#include "string.h"
#include "board.h"
#include "dev_rtu_mb.h"
#include "dev_rtu_virtualIO.h"

static int modbus_dev_rtu_slave_callback(dev_rtu_mb_t* smb, int function_code, int addr, int num, void* read_write_data)
{
    int rc = 0;
    switch (function_code)
    {
        case MODBUS_FC_READ_HOLDING_REGISTERS:
        {
            if ((0 <= addr) && (addr < 125))
            {
                rc = dev_rtu_read_hold_regs(addr, num, read_write_data);
            }
        }
        break;
        case MODBUS_FC_WRITE_SINGLE_REGISTER:
        {
            if ((0 <= addr) && (addr < 125))
            {
                rc = dev_rtu_write_hold_regs(addr, num, read_write_data);
            }
        }
        break;
    }
    if (rc < 0)
    {
        rt_kprintf("callback fail %d\n", rc);
    }
    return rc;
}

static int uart_rts(int on)
{
    return 0;
}

static dev_rtu_mb_t modbus_dev_rtu_slave = {0};

static void modbus_dev_rtu_slave_thread_entry(void* param)
{
    int rc = 0;
    dev_rtu_mb_t* smb_slave = param;
    dev_rtu_mb_init(smb_slave, MODBUS_CORE_RTU, dev_rtu_mb_port_rtdevice_create(SMRTU_UART_DEVICE_NAME));
    struct serial_configure serial_config;
    serial_config.baud_rate = BAUD_RATE_19200;
    serial_config.data_bits = DATA_BITS_8;
    serial_config.stop_bits = STOP_BITS_1;
    serial_config.bufsz = 512;
    serial_config.parity = PARITY_NONE;
    dev_rtu_mb_dev_rtu_set_serial_config(smb_slave, &serial_config);
    dev_rtu_mb_dev_rtu_set_serial_rts(smb_slave, uart_rts);
    dev_rtu_mb_dev_rtu_set_oflag(smb_slave, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
    dev_rtu_mb_set_slave(smb_slave, SMRTU_SLAVE_ADDR);
    dev_rtu_mb_connect(smb_slave);

    for (;;)
    {
        rc = dev_rtu_mb_slave_wait_handle(smb_slave, modbus_dev_rtu_slave_callback, MODBUS_WAIT_FOREVER);
        if (rc > 0)
        {
            continue;
        }
        else
        {
            dev_rtu_mb_error_recovery(smb_slave);
        }
    }
}

int modbus_dev_rtu_slave_thread(void)
{
    rt_thread_t tid;

    tid = rt_thread_create("RTU", modbus_dev_rtu_slave_thread_entry, &modbus_dev_rtu_slave, SMRTU_THREAD_STACK_SIZE, SMRTU_THREAD_PRIORITY, SMRTU_THREAD_TICKS);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
    else
    {
        goto __exit;
    }

    return RT_EOK;
__exit:
    if (tid)
        rt_thread_delete(tid);
    return RT_ERROR;
}
